﻿namespace EFS.RC.CC.Applications.Remote.Operators
{
	/// <summary>
	/// Supervisor session
	/// </summary>
	internal class SupervisorCentral : EFS.RC.CC.Applications.Remote.Application
	{
		#region Composition

		// sync access
		private object syncAccess = new object();

		// Operator
		private EFS.RC.CC.Presences.Operators.OfficeService.Supervisors.Supervisor supervisorPresence = null;

		// Operators Team
		private EFS.RC.CC.Presences.Operators.OfficeService.Team operatorsTeam = null;

		#endregion

		#region Constructor

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="supervisorPresence"></param>
		public SupervisorCentral(EFS.RC.CC.Presences.Operators.OfficeService.Supervisors.Supervisor supervisorPresence, Microsoft.Rtc.Collaboration.InstantMessagingCall supervisorInstantMessagingCall, EFS.RC.CC.Presences.Operators.OfficeService.Team operatorsTeam)
			: base(supervisorInstantMessagingCall)
		{
			// check
			EFS.Common.Verify.Reference(supervisorPresence, "supervisorPresence");
			EFS.Common.Verify.Reference(operatorsTeam, "operatorsTeam");

			// set internals
			this.supervisorPresence = supervisorPresence;
			this.operatorsTeam = operatorsTeam;

			// log
			EFS.EventLog.Log.LogInfo("Supervisor", this);
		}

		#endregion

		#region Usage

		/// <summary>
		/// Describe this object into a nice formated string
		/// </summary>
		/// <returns></returns>
		public override System.String Describe()
		{
			return System.String.Format("EFS.RC.CC.Applications.Remote.Operators [{0}]", base.Describe());
		}

		#endregion

		#region Startup

		/// <summary>
		/// OnEstablished
		/// </summary>
		protected override void OnEstablished()
		{
			// send monitored customer end points
			SendMonitoredApplications();

			// send configs
			SendConfigs();
		}

		#endregion

		#region Runtime

		/// <summary>
		/// OnMessageReceived
		/// </summary>
		/// <param name="message"></param>
		protected override void OnMessageReceived(EFS.RC.CC.Messages.Message message)
		{
			// check monitor
			if (message is EFS.RC.CC.Messages.Supervisor.Tools.Monitor)
			{
				// convert
				EFS.RC.CC.Messages.Supervisor.Tools.Monitor monitorMessage = message as EFS.RC.CC.Messages.Supervisor.Tools.Monitor;

				// find the agent
				EFS.RC.CC.Presences.Operators.OfficeService.Agent agentPresence = supervisorPresence.OfficeServiceOperatorEndPointApplication.OperatorsTeam.GetAgentBySIP(monitorMessage.AgentSIP);

				// must exists
				EFS.Common.Verify.Reference(agentPresence, "agentPresence");

				// get session session
				EFS.RC.CC.Sessions.OfficeService.Operators.Operator operatorSession = agentPresence.OperatorSession;

				// check
				if (null != operatorSession)
				{
					// get customer session
					EFS.RC.CC.Confereces.OfficeService officeServiceConference = operatorSession.CustomerSession.OfficeServiceConference;

					// check
					if (null != officeServiceConference)
					{
						// check
						if (officeServiceConference.IsSupervised())
						{
							// already supervised
							BeginDataSend(new EFS.RC.CC.Messages.Error("This Conference is already Supervised"));
						}
						else
						{
							// begin session
							supervisorPresence.StartSupervisorSession(officeServiceConference);
						}
					}
				}
			}
			// check ACD message
			else if (message is EFS.RC.CC.Messages.Agents.ACD)
			{
				// convert
				EFS.RC.CC.Messages.Agents.ACD acdMessage = message as EFS.RC.CC.Messages.Agents.ACD;

				// find the agent
				EFS.RC.CC.Presences.Operators.OfficeService.Agent agentPresence =
					supervisorPresence.OfficeServiceOperatorEndPointApplication.OperatorsTeam.GetAgentBySIP(acdMessage.AgentSIP);

				// check if still in team
				if (null != agentPresence)
				{
					// get customer end point presence
					EFS.RC.CC.Presences.EndPoints.OfficeService.Customer customerOfficeServiceEndPointPresence =
						supervisorPresence.OfficeServiceOperatorEndPointApplication.ApplicationPresence.EndPointsPresencesRegistrar.GetCustomerOfficeServicePresence(acdMessage.EndPointTel);

					// must exists
					EFS.Common.Verify.Reference(customerOfficeServiceEndPointPresence, "customerOfficeServiceEndPointPresence");

					// check app
					EFS.Common.Verify.Reference(customerOfficeServiceEndPointPresence.PresenceEndPointApplication, "customerOfficeServiceEndPointPresence.PresenceEndPointApplication");

					// check enable / disable
					if (acdMessage.Enable)
					{
						// update -> create
						EFS.RC.CC.Tools.Deployment.Update.Distribution updateDistrubution = new EFS.RC.CC.Tools.Deployment.Update.Distribution(
							agentPresence.OperatorPresenceDeployment.ID.Value,
							customerOfficeServiceEndPointPresence.PresenceEndPointApplication.ApplicationPresence.PresenceEndPointDeployment.ID.Value,
							true);

						// execute database update
						updateDistrubution.Execute();

						// start agent for distribution
						customerOfficeServiceEndPointPresence.PresenceEndPointApplication.AgentsDistribution.AddAgentToDistribution(agentPresence);
					}
					else
					{
						// register
						EFS.RC.CC.Presences.Operators.Distribution.Agent agentDistribution = agentPresence.GetDistributionRegistration(customerOfficeServiceEndPointPresence.PresenceEndPointApplication.AgentsDistribution);

						// end distribute if found
						if (null != agentDistribution)
						{
							// update -> delete
							EFS.RC.CC.Tools.Deployment.Update.Distribution updateDistrubution = new EFS.RC.CC.Tools.Deployment.Update.Distribution(
								agentPresence.OperatorPresenceDeployment.ID.Value,
								customerOfficeServiceEndPointPresence.PresenceEndPointApplication.ApplicationPresence.PresenceEndPointDeployment.ID.Value,
								false);

							// execute database update
							updateDistrubution.Execute();

							// stop register 
							agentDistribution.EndDistribute();
						}
					}
				}
			}
			// check ACD message
			else if (message is EFS.RC.CC.Messages.Application.Command)
			{
				// update -> create
				EFS.RC.CC.Tools.Control.Command command = new EFS.RC.CC.Tools.Control.Command(
					(message as EFS.RC.CC.Messages.Application.Command).Text,
					this);

				// execute database update
				command.Execute();
			}
		}

		/// <summary>
		/// Send monitored applications list
		/// </summary>
		private void SendMonitoredApplications()
		{
			try
			{
				supervisorPresence.OfficeServiceOperatorEndPointApplication.ApplicationPresence.EndPointsPresencesRegistrar.ForeachCustomerOfficeServicePresence(SendMonitoredApplication);
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);

				// shutdown
				BeginShutdown();
			}
		}

		/// <summary>
		/// Send configs
		/// </summary>
		private void SendConfigs()
		{
			try
			{
				// get config
				EFS.RC.CC.Messages.Application.Configs.CH chConfig = new Messages.Application.Configs.CH();
				chConfig.ConnectionString = EFS.RC.CC.CH.Config.Settings.QrdConnectionString;

				// send
				BeginDataSend(chConfig);
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);

				// shutdown
				BeginShutdown();
			}
		}
		/// <summary>
		/// Send monitored applications list
		/// </summary>
		private void SendMonitoredApplication(EFS.RC.CC.Presences.EndPoints.OfficeService.Customer customersOfficeServiceEndPointPresence)
		{
			// check
			EFS.Common.Verify.Reference(customersOfficeServiceEndPointPresence, "customersOfficeServiceEndPointPresence");

			// check if active
			if (null != customersOfficeServiceEndPointPresence.PresenceEndPointApplication)
			{
				// make new message
				EFS.RC.CC.Messages.Application.CustomerEndPoint customerEndPointsupervisorMessage = new EFS.RC.CC.Messages.Application.CustomerEndPoint();

				// set
				customerEndPointsupervisorMessage.PhoneUri = customersOfficeServiceEndPointPresence.PresenceEndPointDeployment.URI;
				customerEndPointsupervisorMessage.RequiredSkillId = customersOfficeServiceEndPointPresence.PresenceEndPointDeployment.SkillID.Value;

				// send
				BeginDataSend(customerEndPointsupervisorMessage);
			}
		}

		#endregion // Runtime

		#region Shutdown

		#endregion
	}
}

